package com.hwpt.hwaccount.core.utils;

import android.util.Log;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {
    private static final String TAG = "JwtUtils";
    
    // 默认密钥，实际应用中应从安全配置中获取
    private static final String DEFAULT_SECRET = "ithanvon";
    
    // JWT有效期（毫秒），默认1小时
    private static final long EXPIRATION_TIME = 3600000;
    
    // 创建算法实例
    private static Algorithm getAlgorithm() {
        return Algorithm.HMAC256(DEFAULT_SECRET);
    }

    /**
     * 生成JWT
     * @param claims 自定义声明
     * @return JWT字符串
     */
    public static String generateToken(Map<String, Object> claims) {
        try {
            long currentTime = System.currentTimeMillis();

            // 创建JWT Builder
            com.auth0.jwt.JWTCreator.Builder builder = JWT.create();

            // 添加自定义声明
            for (Map.Entry<String, Object> entry : claims.entrySet()) {
                if (entry.getValue() instanceof String) {
                    builder.withClaim(entry.getKey(), (String) entry.getValue());
                } else if (entry.getValue() instanceof Integer) {
                    builder.withClaim(entry.getKey(), (Integer) entry.getValue());
                } else if (entry.getValue() instanceof Long) {
                    builder.withClaim(entry.getKey(), (Long) entry.getValue());
                } else if (entry.getValue() instanceof Boolean) {
                    builder.withClaim(entry.getKey(), (Boolean) entry.getValue());
                } else if (entry.getValue() instanceof Double) {
                    builder.withClaim(entry.getKey(), (Double) entry.getValue());
                } else if (entry.getValue() instanceof Date) {
                    builder.withClaim(entry.getKey(), (Date) entry.getValue());
                }
            }

            // 设置签发时间和过期时间
            return builder
                    .withIssuedAt(new Date(currentTime))
                    .withExpiresAt(new Date(currentTime + EXPIRATION_TIME))
                    .sign(getAlgorithm());
        } catch (Exception e) {
            Log.e(TAG, "生成JWT时出错: " + e.getMessage());
            return null;
        }
    }
    
    /**
     * 解析JWT
     * @param token JWT字符串
     * @return 解析后的JWT对象
     */
    public static DecodedJWT parseToken(String token) {
        try {
            return JWT.decode(token);
        } catch (Exception e) {
            Log.e(TAG, "解析JWT时出错: " + e.getMessage());
            return null;
        }
    }
    
    /**
     * 验证JWT是否有效且未过期
     * @param token JWT字符串
     * @return 验证结果
     */
    public static boolean validateToken(String token) {
        try {
            JWTVerifier verifier = JWT.require(getAlgorithm()).build();
            verifier.verify(token);
            return true;
        } catch (TokenExpiredException e) {
            Log.e(TAG, "Token已过期: " + e.getMessage());
            return false;
        } catch (JWTVerificationException e) {
            Log.e(TAG, "Token验证失败: " + e.getMessage());
            return false;
        } catch (Exception e) {
            Log.e(TAG, "验证JWT时出错: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 检查JWT是否过期
     * @param token JWT字符串
     * @return 是否过期
     */
    public static boolean isTokenExpired(String token) {
        try {
            DecodedJWT jwt = parseToken(token);
            if (jwt != null) {
                return jwt.getExpiresAt().before(new Date());
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "检查Token过期时出错: " + e.getMessage());
            return true;
        }
    }

    /**
     * 获取JWT中的用户名（如果存在）
     * @param token JWT字符串
     * @return 用户名或null
     */
    public static String getUsernameFromToken(String token) {
        try {
            DecodedJWT jwt = parseToken(token);
            if (jwt != null) {
                Claim usernameClaim = jwt.getClaim("username");
                if (!usernameClaim.isNull()) {
                    return usernameClaim.asString();
                }
            }
            return null;
        } catch (Exception e) {
            Log.e(TAG, "获取用户名时出错: " + e.getMessage());
            return null;
        }
    }
    
    /**
     * 获取JWT过期时间
     * @param token JWT字符串
     * @return 过期时间或null
     */
    public static Date getExpirationDateFromToken(String token) {
        try {
            DecodedJWT jwt = parseToken(token);
            if (jwt != null) {
                return jwt.getExpiresAt();
            }
            return null;
        } catch (Exception e) {
            Log.e(TAG, "获取过期时间时出错: " + e.getMessage());
            return null;
        }
    }
    
    /**
     * 获取JWT签发时间
     * @param token JWT字符串
     * @return 签发时间或null
     */
    public static Date getIssuedAtFromToken(String token) {
        try {
            DecodedJWT jwt = parseToken(token);
            if (jwt != null) {
                return jwt.getIssuedAt();
            }
            return null;
        } catch (Exception e) {
            Log.e(TAG, "获取签发时间时出错: " + e.getMessage());
            return null;
        }
    }
    
    /**
     * 获取JWT的所有声明
     * @param token JWT字符串
     * @return 声明Map或空Map
     */
    public static Map<String, Claim> getAllClaimsFromToken(String token) {
        try {
            DecodedJWT jwt = parseToken(token);
            if (jwt != null) {
                return jwt.getClaims();
            }
            return new HashMap<>();
        } catch (Exception e) {
            Log.e(TAG, "获取所有声明时出错: " + e.getMessage());
            return new HashMap<>();
        }
    }
    
    /**
     * 获取JWT的详细验证结果
     * @param token JWT字符串
     * @return 验证结果消息
     */
    public static String getValidationDetails(String token) {
        try {
            JWTVerifier verifier = JWT.require(getAlgorithm()).build();
            verifier.verify(token);
            return "Token有效";
        } catch (TokenExpiredException e) {
            return "Token已过期";
        } catch (JWTVerificationException e) {
            return "Token验证失败: " + e.getMessage();
        } catch (Exception e) {
            return "Token验证出错: " + e.getMessage();
        }
    }
    
    /**
     * 刷新Token（创建新Token，保留原声明）
     * @param token 原JWT字符串
     * @return 新JWT字符串或null
     */
    public static String refreshToken(String token) {
        try {
            DecodedJWT jwt = parseToken(token);
            if (jwt != null) {
                Map<String, Object> claims = new HashMap<>();
                
                // 复制所有声明
                Map<String, Claim> originalClaims = jwt.getClaims();
                for (Map.Entry<String, Claim> entry : originalClaims.entrySet()) {
                    String key = entry.getKey();
                    Claim claim = entry.getValue();
                    
                    if (!"iat".equals(key) && !"exp".equals(key)) {
                        if (claim.asString() != null) {
                            claims.put(key, claim.asString());
                        } else if (claim.asBoolean() != null) {
                            claims.put(key, claim.asBoolean());
                        } else if (claim.asInt() != null) {
                            claims.put(key, claim.asInt());
                        } else if (claim.asLong() != null) {
                            claims.put(key, claim.asLong());
                        } else if (claim.asDouble() != null) {
                            claims.put(key, claim.asDouble());
                        } else if (claim.asDate() != null) {
                            claims.put(key, claim.asDate());
                        }
                    }
                }
                
                return generateToken(claims);
            }
            return null;
        } catch (Exception e) {
            Log.e(TAG, "刷新Token时出错: " + e.getMessage());
            return null;
        }
    }
}